<template>
  <div :class="{'el-input':simple}" :style="style">
    <div class="el-input">
      <el-input :value="valueName" class="search-panel" :disabled="disabled" readonly :placeholder="placeholder">
        <template #suffix>
      <span @click="OpenFilterPanel">
        {{ buttonName ? buttonName : '选择' }}
      </span>
        </template>
      </el-input>
    </div>
    <app-table v-if="simple===false && choiceRaw.length>0" :data="choiceRaw" :columns="columns.concat([{'type':'action',width: '75px',align: 'center',fixed: 'right'}])">
      <template #action="{ row }">
        <el-button type="danger" size="small" @click="removeValue(row)">移除</el-button>
      </template>
    </app-table>
  </div>
</template>
<script lang="ts">
import {computed, defineComponent, PropType, SlotsType, h, defineAsyncComponent, ref, UnwrapRef, Ref} from "vue"
import request from "@/units/request";
import {usePopupComponent} from "@/components/FunctionComponents";
import {TableColumn} from "@/components/AppTable/TableType";
import {CloneData, isEmpty, typeOf} from "@/units/tool";

export default defineComponent({
  name: "SearchPanel",
  slots: Object as SlotsType<{ where: {} }>,
  emits: ['update:modelValue', 'change', 'input'],
  props: {
    modelValue: {
      type: [String, Number, Array],
      required: true
    },
    title: {
      type: String,
      default: '数据搜索'
    },
    api: {//请求地址
      type: String,
      required: true
    },
    query: {//添加默认搜索条件
      type: Object as PropType<{ [key: string]: any }>,
      default() {
        return {}
      }
    },
    simple: {//简单模式
      type: Boolean,
      default: true
    },
    disabled: {//是否禁用
      type: Boolean,
      default: false
    },
    buttonName: {//按钮名称
      type: String,
      default: '选择'
    },
    placeholder: {//输入框提示
      type: String,
      default: '请输入后关键词'
    },
    width: {
      type: String,
      default: '640px'
    },
    multiple: {//是否是什么值 true多选  false单选
      type: Boolean,
      default: false
    },
    columns: {//表单配置列
      type: Array as PropType<Array<TableColumn>>,
      default() {
        const columns: Array<TableColumn> = [
          {prop: "id", label: "ID"},
          {prop: "name", label: "名称"}
        ]
        return columns
      }
    },
    valueKey: {//表值内容key
      type: String,
      default: 'id'
    },
    labelKey: {//表单显示内容key
      type: String,
      default: 'name'
    }
  },
  setup(props, {slots, emit}) {
    /**
     * 当前选中数据展示
     */
    const choice: Ref<UnwrapRef<Array<{ value: string | number, label: string }>>> = ref([])

    //选中的原始数据
    const choiceRaw: Ref<any[]> = ref([])

    const style = computed(() => {
      return props.simple ? {} : {width: "100%"}
    })


    if (!isEmpty(props.modelValue)) {
      request(props.api, {
        ...props.query,
        value: props.modelValue,
        page: 1, size: 1000
      }).then(result => {
        if (result.code === 200) {
          clearValue()
          choice.value = []
          if (result.data.list.length > 0) {
            choiceRaw.value = result.data.list
            setTimeout(() => {
              HandleValue(props.multiple ? result.data.list : result.data.list[0])
            }, 10)
          }
        }
      })
    }


    function clearValue() {
      if (props.disabled) return
      if (props.multiple) {
        setValue([])
      } else {
        setValue('')
      }
    }


    /**
     * 设置所选值
     */
    function setValue(val: any | any[]) {
      emit('change', val)
      emit('input', val)
      emit('update:modelValue', val)
    }


    /**
     * 处理回调数据
     * @param val
     * @constructor
     */
    function HandleValue(val: any | any[]) {
      if (props.multiple && typeOf(val) === 'array') {//多选
        let NewValue: Array<string | number> = typeOf(props.modelValue) === 'array' ? CloneData(props.modelValue) : []
        for (let item of val) {
          let _val = item[props.valueKey]
          if (NewValue.indexOf(_val) === -1) {
            NewValue.push(_val)
            choice.value.push({label: item[props.labelKey], value: _val})
          }
        }
        setValue(NewValue)
      } else if (!props.multiple && typeOf(val) === 'object') {//单选
        choice.value = [{label: val[props.labelKey], value: val[props.valueKey]}]
        choiceRaw.value = [{...val}]
        setValue(val[props.valueKey])
      }
    }


    /**
     * 打开搜索面板
     * @constructor
     */
    function OpenFilterPanel() {
      usePopupComponent(
          undefined,
          h(
              defineAsyncComponent((): any => import("./DataPanel.vue")),
              {
                api: props.api,
                title: props.title,
                query: props.query,
                columns: props.columns,
                multiple: props.multiple,
                choice: choice.value,
                onChoice: (val: any) => {
                  HandleValue(val)
                },
                //移出回调
                onUpdateChoice: (val: Array<{ value: string | number, label: string }>) => {
                  choice.value = val
                  if (props.multiple) {
                    setValue(val.map(item => item.value))
                  } else {
                    setValue(val[0]?.value ? val[0]?.value : '')
                    choiceRaw.value = []
                  }
                }
              },
              {
                ...slots
              }
          ),
          props.width
      )
    }

    /**
     * 显示值
     */
    const valueName = computed(() => {
      if (choice.value.length === 0) {
        return ''
      }
      if (props.multiple) {
        let val = []
        for (let item of choice.value) {
          val.push(item.label)
          if (val.length >= 2) {
            break;
          }
        }
        if (choice.value.length > 2) {
          val.push(` +${choice.value.length - 2}`)
        }
        return val.join(' / ')
      }
      return choice.value[0].label
    })


    /**
     * 移除值
     */
    function removeValue(row) {
      if (props.multiple) {
        console.log('待完成');
      } else {
        setValue('')
        choice.value = []
        choiceRaw.value = []
      }
    }

    return {
      OpenFilterPanel,
      valueName,
      slots,
      choiceRaw,
      style,
      removeValue
    }
  }
})
</script>
<style lang="scss" scoped>
.search-panel {
  :deep(.el-input__suffix-inner) {
    span {
      line-height: 1;
      cursor: pointer;
      color: var(--el-color-primary);

      &:hover {
        color: var(--el-color-primary-light-3);
      }
    }
  }
}
</style>